package com.smallrig.mall.template.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smallrig.mall.template.entity.Order;
import com.smallrig.mall.template.mapper.OrderMapper;
import com.smallrig.mall.template.mapper.ProductMapper;
import com.smallrig.mall.template.service.OrderService;
import com.smallrig.mall.template.state.OrderStatus;
import com.smallrig.mall.template.state.OrderStatusChangeEvent;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.weaver.ast.Or;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.scheduling.annotation.Async;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@Service
@Slf4j
public class OrderServiceImpl  extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private ProductMapper productMapper;

    @Override
    public void saveOrder(){
        Order order = new Order();
        order.setOrderSn(2L);
        order.setProductId(1);
        order.setUserId(1);
        order.setBuyNum(1);
        orderMapper.save(order);
    }

    @Override
    @Transactional
    public boolean saveOrder(List<Order> orders){
        int sum = orders.stream().mapToInt(e -> e.getBuyNum()).sum();
        //扣减库存，生成订单
        int affect = orderMapper.saveBatch(orders);

        int aff = productMapper.decrStock(orders.get(0).getProductId(), sum);
        //失败处理 todo
        if(aff<=0){
            log.error("扣减库存失败");
        }
        if(affect!=orders.size()){
            log.error("保存订单失败");
        }
        return aff>0;
    }
//    @Resource
//    private StateMachineFactory<OrderStatus, OrderStatusChangeEvent> orderStateMachineFactory;
//    public static final String stateMachineId = "orderStateMachine";
    @Resource
    private StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine;

    @Resource
    private StateMachinePersister<OrderStatus, OrderStatusChangeEvent, Order> persister;

    @Override
    @Async
    public Order testAsync(){
        Order order = new Order();
        order.setId(1);
        return order;
    }


    @Override
    @Async
    public Future<Order> testAsyncFuture(){
        Order order = new Order();
        order.setId(1);
        return CompletableFuture.completedFuture(order);
    }

    @Override
    @Async
    public Future<Order> testNestedAsync() throws ExecutionException, InterruptedException {
        Future<Order> orderFuture = testAsyncFuture();
        return CompletableFuture.completedFuture(orderFuture.get());
    }

    @Override
    public Order pay(int id) {
        Order order = getById(id);
        System.out.println("threadName=" + Thread.currentThread().getName() + " 尝试支付 id=" + id);
        Message message = MessageBuilder.withPayload(OrderStatusChangeEvent.PAYED).setHeader("order", order).build();
        if (!sendEvent(message, order)) {
            System.out.println("threadName=" + Thread.currentThread().getName() + " 支付失败, 状态异常 id=" + id);
        }
        return order;
    }

    @Override
    public Order deliver(int id) {
        Order order = getById(id);
        System.out.println("threadName=" + Thread.currentThread().getName() + " 尝试发货 id=" + id);
        if (!sendEvent(MessageBuilder.withPayload(OrderStatusChangeEvent.DELIVERY).setHeader("order", order).build(), order)) {
            System.out.println("threadName=" + Thread.currentThread().getName() + " 发货失败，状态异常 id=" + id);
        }
        return order;
    }

    @Override
    public Order receive(int id) {
        Order order = getById(id);
        System.out.println("threadName=" + Thread.currentThread().getName() + " 尝试收货 id=" + id);
        if (!sendEvent(MessageBuilder.withPayload(OrderStatusChangeEvent.RECEIVED).setHeader("order", order).build(), order)) {
            System.out.println("threadName=" + Thread.currentThread().getName() + " 收货失败，状态异常 id=" + id);
        }
        return order;
    }



    /**
     * 发送订单状态转换事件
     *
     * @param message
     * @param order
     * @return
     */
    private synchronized boolean sendEvent(Message<OrderStatusChangeEvent> message, Order order) {
        boolean result = false;
//        StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine = orderStateMachineFactory.getStateMachine(stateMachineId);
        try {
//            orderStateMachine.start();
            //尝试恢复状态机状态
//            persister.restore(orderStateMachine, order);
            //添加延迟用于线程安全测试
//            Thread.sleep(1000);
            result = orderStateMachine.sendEvent(message);
            //持久化状态机状态
//            persister.persist(orderStateMachine, order);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//            orderStateMachine.stop();
        }
        return result;
    }

}
